#include "stdafx.h"
#include "Schedule.h"
#include <iostream>

using namespace std;

/*------------------------------------------------------------
/ Schedule
/ Description: default constructor 
/ Parameters: N/A
/ Return: N/A
------------------------------------------------------------*/
Schedule::Schedule(void)
{
	dailyFlightsArrival = new std::list<Flight> ();
	weeklyFlightsArrival = new std::list<Flight> ();
	oneTimeFlightsArrival = new std::list<Flight> ();
	dailyFlightsDeparture = new std::list<Flight> ();
	weeklyFlightsDeparture = new std::list<Flight> ();
	oneTimeFlightsDeparture = new std::list<Flight> ();
}

/*------------------------------------------------------------
/ ~Schedule
/ Description: default destructor 
/ Parameters: N/A
/ Return: N/A
------------------------------------------------------------*/
Schedule::~Schedule(void)
{
}

/*----------------DAILY-------------------------------------*/
/*------------------------------------------------------------
/ addDailyFlight
/ Description: adds newFlight into list of daily Flights
/ Parameters: newFlight: Flight being added to Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::AddDailyFlight (Flight newFlight){
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (dailyFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (dailyFlightsArrival, newFlight);	
	}
}

/*------------------------------------------------------------
/ deleteDailyFlight
/ Description: removes newFlight from list of daily flights
/ Parameters: newFlight: Flight being removed from Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::DeleteDailyFlight (Flight newFlight){
	deleteSpecific (dailyFlightsDeparture, newFlight);
}

/*------------------------------------------------------------
/ modifyDailyFlight
/ Description: replaces oldFlight with newFlight in list of daily Flights
/ Parameters: oldFlight: Flight being modified
/			  newFlight: Flight after modifications
/ Return: N/A
------------------------------------------------------------*/
void Schedule::ModifyDailyFlight (Flight oldFlight, Flight newFlight){
	deleteSpecific (dailyFlightsDeparture, newFlight);
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (dailyFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (dailyFlightsArrival, newFlight);	
	}
}

/*----------------WEEKLY-------------------------------------*/
/*------------------------------------------------------------
/ addWeeklyFlight
/ Description: adds newFlight into list of weekly Flights
/ Parameters: newFlight: Flight being added to Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::AddWeeklyFlight (Flight newFlight){
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (weeklyFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (weeklyFlightsArrival, newFlight);	
	}
}

/*------------------------------------------------------------
/ deleteWeeklyFlight
/ Description: removes newFlight from list of weekly Flights
/ Parameters: newFlight: Flight being removed from Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::DeleteWeeklyFlight (Flight newFlight){
	deleteSpecific (weeklyFlightsDeparture, newFlight);
}

/*------------------------------------------------------------
/ modifyWeeklyFlight
/ Description: replaces oldFlight with newFlight in list of weekly Flights
/ Parameters: oldFlight: Flight being modified
/			  newFlight: Flight after modifications
/ Return: N/A
------------------------------------------------------------*/
void Schedule::ModifyWeeklyFlight (Flight oldFlight, Flight newFlight){
	deleteSpecific (weeklyFlightsArrival, newFlight);	
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (weeklyFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (weeklyFlightsArrival, newFlight);	
	}
}

/*----------------ONE TIME-------------------------------------*/
/*------------------------------------------------------------
/ addOneTimeFlight
/ Description: adds newFlight into list of one-time Flights
/ Parameters: newFlight: Flight being added to Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::AddOneTimeFlight (Flight newFlight){
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (oneTimeFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (oneTimeFlightsArrival, newFlight);	
	}
}

/*------------------------------------------------------------
/ deleteOneTimeFlight
/ Description: removes newFlight from list of one-time Flights
/ Parameters: newFlight: Flight being removed from Schedule
/ Return: N/A
------------------------------------------------------------*/
void Schedule::DeleteOneTimeFlight (Flight newFlight){
	deleteSpecific (oneTimeFlightsArrival, newFlight);	
}

/*------------------------------------------------------------
/ modifyOneTimeFlight
/ Description: replaces oldFlight with newFlight in list of one-time Flights
/ Parameters: oldFlight: Flight being modified
/			  newFlight: Flight after modifications
/ Return: N/A
------------------------------------------------------------*/
void Schedule::ModifyOneTimeFlight (Flight oldFlight, Flight newFlight){
	deleteSpecific (oneTimeFlightsArrival, newFlight);	
	if (newFlight.getArrivalTime() == NULL){
		insertInOrderDeparture (oneTimeFlightsDeparture, newFlight);
	}else{
		insertInOrderArrival (oneTimeFlightsArrival, newFlight);	
	}
}

list<Flight>* Schedule::getOneTimeInFlights(){
	return oneTimeFlightsArrival;
}

list<Flight>* Schedule::getDailyInFlights(){
	return dailyFlightsArrival;
}

list<Flight>* Schedule::getWeeklyInFlights(){
	return weeklyFlightsArrival;
}

list<Flight>* Schedule::getOneTimeOutFlights(){
	return oneTimeFlightsDeparture;
}

list<Flight>* Schedule::getDailyOutFlights(){
	return dailyFlightsDeparture;
}

list<Flight>* Schedule::getWeeklyOutFlights(){
	return weeklyFlightsDeparture;
}

/* -----------------------OTHER METHODS ---------------------------*/

/* Inserting into the departure list 
*
*
*
*
*/
void Schedule::insertInOrderDeparture(std::list<Flight> *tempList, Flight fObj){
  std::list<Flight>::iterator it;
  int flag = 0;

  //if the list is empty, just add it
  if (tempList->empty()){
	tempList->push_back(fObj);

  //if the list is not empty, search for proper location
  }else{
		it = tempList->begin();

		//find the position for the flight object in the list
		while (!flag && it != tempList->end()){

			/* ADD IN THE INFORMATION FOR DATE, WHEN IT BECOMES AVAILABLE
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			*/

			//Checks if hour of current node is earlier than flight object 
			if (it->getDepartureTime()->getH() > fObj.getDepartureTime()->getH()){
				it++; //move to next node

			//if hours are equal check minutes
			} else if (it->getDepartureTime()->getH() == fObj.getDepartureTime()->getH()) {
				if (it->getDepartureTime()->getM() > fObj.getDepartureTime()->getM()){
					it++; //move to next node
				} else {
					flag++; //found the correct position for the flight object
				}
			} else {
				flag++; //found the correct position for the flight object
			}
		}

		//compare against the last element of the list
		if (!flag){
			//if the hours are earlier, this is the spot so set flag
			if (!(it->getDepartureTime()->getH() > fObj.getDepartureTime()->getH())){
				flag ++;
			//if not, check minutes
			}else{
				//the hours are the same, see if minutes are before, if so, we found our spot
				if (it->getDepartureTime()->getH() == fObj.getDepartureTime()->getH()){
					if (!(it->getDepartureTime()->getM() > fObj.getDepartureTime()->getM())){
						flag ++;
					}
				}	
			}
		}

		//if spot has been found, add to location
		if (flag){
			tempList->insert(it,fObj);

		//if no spot found, add to the end of the list
		}else{
			tempList->push_back(fObj);
		}
  }
}

/* Inserting into the arrival list 
*
*
*
*
*/
void Schedule::insertInOrderArrival(std::list<Flight> *tempList, Flight fObj){
  std::list<Flight>::iterator it;
  int flag = 0;

  //if the list is empty, just add it
  if (tempList->empty()){
	tempList->push_back(fObj);

  //if the list is not empty, search for proper location
  }else{
		it = tempList->begin();

		//find the position for the flight object in the list
		while (!flag && it != tempList->end()){

			/* ADD IN THE INFORMATION FOR DATE, WHEN IT BECOMES AVAILABLE
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			* DO NOT FORGET!!!!!!!!!!!!!!!!!!!!!
			*/

			//Checks if hour of current node is earlier than flight object 
			if (it->getArrivalTime()->getH() > fObj.getArrivalTime()->getH()){
				it++; //move to next node

			//if hours are equal check minutes
			} else if (it->getArrivalTime()->getH() == fObj.getArrivalTime()->getH()) {
				if (it->getArrivalTime()->getM() > fObj.getArrivalTime()->getM()){
					it++; //move to next node
				} else {
					flag++; //found the correct position for the flight object
				}
			} else {
				flag++; //found the correct position for the flight object
			}
		}

		//compare against the last element of the list
		if (!flag){
			//if the hours are earlier, this is the spot so set flag
			if (!(it->getArrivalTime()->getH() > fObj.getArrivalTime()->getH())){
				flag ++;
			//if not, check minutes
			}else{
				//the hours are the same, see if minutes are before, if so, we found our spot
				if (it->getArrivalTime()->getH() == fObj.getArrivalTime()->getH()){
					if (!(it->getArrivalTime()->getM() > fObj.getArrivalTime()->getM())){
						flag ++;
					}
				}	
			}
		}

		//if spot has been found, add to location
		if (flag){
			tempList->insert(it,fObj);

		//if no spot found, add to the end of the list
		}else{
			tempList->push_back(fObj);
		}
  }
}

/* Deleting from either arrival or departure 
*
*
*
*
*/
int Schedule::deleteSpecific (std::list<Flight> *tempList, Flight fObj){
  std::list<Flight>::iterator it;
  int flag = 0;

  //if the list is empty, just add it
  if (tempList->empty()){
	 std::cout << "ERROR IN SCHEDULE.CPP, THE ITEM ATTEMPTED TO BE REMOVED FOR DOESNT EXIST! SHOULD NEVER HAPPEN!" << std::endl;
	 return -1; //The List Is Empty, the item does not exist ERROR

  //if the list is not empty, search for proper location
  }else{
		it = tempList->begin();

		//find the position for the flight object in the list
		while (it != tempList->end()){
			if (it->getFlightID() == fObj.getFlightID()){
				tempList->erase(it);
				return 1;
			}
		}
		   
		//compare against the last element of the list, if it is equal, remove it
		if (it->getFlightID() == fObj.getFlightID()){
			tempList->erase(it);
			return 1;
		//if not equal, error
		}else{
			std::cout << "ERROR IN SCHEDULE.CPP, THE ITEM ATTEMPTED TO BE REMOVED FOR DOESNT EXIST! SHOULD NEVER HAPPEN!" << std::endl;
			return -1;
		}
  }
}
